package main

import (
	"fmt"
	"strings"
)

// 闭包，相当于类和对象 ~
// 返回的是一个函数，匿名函数引用到函数外的n,里面的匿名函数和n 形成一个整体，构成闭包
func main() {

	//testAddUpper()
	//
	//testMakeSuffix()
	//
	//testJob()

	testConcat()

	//testClazz()

}
func testAddUpper() {
	//相当于返回了一个对象，里面的n初始化为10
	upper := addUpper()
	fmt.Println(upper(11)) //21
	fmt.Println(upper(33)) //54

}

// addUpper
//
//		@Description: 返回的是一个函数，匿名函数引用到函数外的n,里面的匿名函数和n 形成一个整体，构成闭包
//	 理解：闭包是类，函数是操作，n是字段 ，多次调用n值初始化一次
//		@return func(int) int
func addUpper() func(int) int {
	var n int = 10
	return func(x int) int {
		n = n + x
		return n
	}
}

func testMakeSuffix() {
	//里面的suffix初始化为 .jpg
	suffix := makeSuffix(".jpg")
	fmt.Println(suffix("hello.jpg")) //hello.jpg
	fmt.Println(suffix("test"))      //test.jpg
}

// makeSuffix
//
//	@Description: 有指定后缀名，直接返回，没有则拼接上后缀名
//	@param suffix 文件后缀名
//	@return func(string) string
func makeSuffix(suffix string) func(string) string {

	//fileName 文件名称
	//-
	//resFileName 返回的文件名称
	return func(fileName string) (resFileName string) {
		if strings.HasSuffix(fileName, suffix) {
			resFileName = fileName
		} else {
			resFileName = fileName + suffix
		}
		return
	}
}

func testJob() {
	devJob := job("java开发", 8000.0)
	employeeNo, fullName, fullSal := devJob("张三", 2000.0)
	fmt.Printf("employeeNo=%v fullName=%v fullSal=%v \n", employeeNo, fullName, fullSal)
	//employeeNo=1 fullName=java开发:张三 fullSal=10000

	employeeNo1, fullName1, fullSal1 := devJob("lisi", 3000.0)
	fmt.Printf("employeeNo=%v fullName=%v fullSal=%v \n", employeeNo1, fullName1, fullSal1)
	//employeeNo=2 fullName=java开发:lisi fullSal=11000
}

// jobFunc
//
//	@Description: 传入员工名称和奖金，返回员工编号、员工全称、最终工资
//	@param jobName 职位名称
//	@param baseSal 基础工资
//	@return  func(string, float64) (int, string, float64)
func job(jobName string, baseSal float64) func(string, float64) (int, string, float64) {
	//员工编号
	var no int

	//employeeName 员工名称
	//bonus 奖金
	//-
	//employeeNo 员工编号
	//fullName 员工全称
	//employeeNo 最终工资
	return func(employeeName string, bonus float64) (employeeNo int, fullName string, fullSal float64) {
		no++
		employeeNo = no
		fullName = jobName + ":" + employeeName
		fullSal = baseSal + bonus
		return
	}

}

func testConcat() {

	concat01 := concat("[BASE]")
	fmt.Println(concat01("aaa"))
	fmt.Println(concat01("bbb"))
	fmt.Println(concat01("ccc"))

}

func concat(s0 string) func(s1 string) (s2 string) {

	//base一直叠加
	return func(s1 string) (s2 string) {
		s2 = s0 + s1
		s0 = s2
		return
	}

}

func concatAlways(so string) func(s1 string) (s2 string) {

	return func(s1 string) (s2 string) {
		s2 = so + s1
		so = s2
		return
	}

}

func testClazz() {
	class := Class("火箭一班")
	class("张三", "001")
	class("李四", "002")
	class("王五", "003")
	clazz := class("赵六", "004")
	fmt.Println(clazz)
}

// Class
//
//	@Description:
//	@param clzName 班级名称
//	@return func(string, string) Clazz
func Class(clzName string) func(string, string) Clazz {
	//构建一个空的班级
	cls := Clazz{
		ClzName: clzName,
		StuList: []Student{},
	}
	//返回一个函数，函数的参数是学生姓名和学号，返回一个班级
	return func(name string, no string) Clazz {
		stu := Student{
			Name: name,
			No:   no,
		}
		cls.StuList = append(cls.StuList, stu)
		return cls
	}
}

type Clazz struct {
	ClzName string
	StuList []Student
}

type Student struct {
	Name string
	No   string
}
